/*
 * Copyright (c) 2017, AEye
 * All rights reserved.
 */

#ifndef AEYE_SOCKET_FRAME_READER_HPP
#define AEYE_SOCKET_FRAME_READER_HPP

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "PointCloudFrame.hpp"
#include "RangingFrameData.h"
#include "QueueManager.hpp"
#include "SocketReaderDetail.hpp"

namespace aeye {
  
  class SocketCloudReader {
  public:

    SocketCloudReader(const std::string& sensorAddr, uint16_t clientPort, bool udpBroadcastMode);
    ~SocketCloudReader() noexcept;

    void run();
    void start();
    void stop() noexcept;
    PointCloudFrame pop();
    void pushPcapPacket(std::vector<uint8_t>&& data);
    void setPcapMode(bool value) noexcept;
    void resetReader();

  private:
    std::atomic<bool> isRunning{false};
    bool pcapModeOn = false;
    Reader reader_;
    QueueManager<std::vector<uint8_t>, QueueType::Waiting> pcap_queue_manager_;
    QueueManager<PointCloudFrame, QueueType::Overwriting> frame_queue_manager_;

    std::string sensorAddress;

    static constexpr size_t maxQueueSize = 3;

    /////////////////////////////////////////////////////////////////////////
    // we will accommodate up to 2 frames of data being accumulated at once.
    // the idea being we might receive a few packets of Frame N + 1 while
    //  still working on finishing up Frame N
    RangingFrameData currentlyAccumulatingFrame;
    bool frameCompleted = false;

    //////////////////////////////////////////////////////////////
    PointCloudFrame currPointCloudFrame;
    uint32_t numPointsInCurrentlyAccumulatingFrame = 0;

    bool processPacket(const uint8_t* data, size_t len);
    bool processPointCloudPacketPayload(const PacketHeader& packetHeader,
                                        const PointReturnsBody& packetBody,
                                        const uint8_t* pData, size_t numPoints);
    void pushRangingFrameToQueue(uint32_t expectedNumberOfPointsInFrame, Pose sensor_pose, const std::string& shotlist_name);

  };
  
}

#endif // AEYE_SOCKET_FRAME_READER_HPP
